home *** CD-ROM | disk | FTP | other *** search
- /* ObText.c
- * ©1992 Working Software, Inc.
- * This source code is copyrighted. Permission is granted to use the Word Services
- * portion of the Writeswell Jr. source code in your own programs, but you
- * may not distribute the Writeswell Jr. word-processor code as a
- * commercial product. If you modify the code, please do not call it
- * Writeswell Jr. (or Writeswell.) This will ensure that people understand the
- * program and don’t have to deal with a number of different versions with
- * who-knows-what going on in the code.
- *
- * Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
- * 26 Dec 91 Mike Crawford
- */
-
- #include <AppleEvents.h>
- #include <AEObjects.h>
- #include <AEPackObject.h>
- #include <AERegistry.h>
- #include "AppEvents.h"
- #include "WordServices.h"
- #include "ObWind.h"
- #include "ObText.h"
- #include "Gripe.h"
- #include "Scroll.h"
- #include "TBConstants.h"
- #include "TBGlobals.h"
-
- /* Given the the direct object of an event is a TextEdit text token (or property thereof),
- * do the requested event.
- */
-
- OSErr DispatchTEText( AEDesc *tokenPtr,
- AppleEvent *theAppleEventPtr,
- AppleEvent *replyEventPtr,
- long refCon )
- {
- OSErr err;
- AEEventClass theClass;
- AEEventID theID;
-
- /* This function is only for the Core suit. Get the event ID from the appleEvent
- */
-
- err = GetEventID( theAppleEventPtr, &theID );
-
- switch ( theID ){
- case kAEGetData:
- err = TETextGetDataHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
- break;
- case kAESetData:
- err = TETextSetDataHandler( tokenPtr, theAppleEventPtr, replyEventPtr, refCon );
- break;
- default:
- err = errAEEventNotHandled;
- break;
- }
-
- return noErr;
- }
-
- /*
- * Event Handlers
- */
-
- /* Get Data */
-
- OSErr TETextGetDataHandler( AEDesc *tokenPtr,
- AppleEvent *theAppleEventPtr,
- AppleEvent *replyEventPtr,
- long refCon )
- {
- TEHandle textH;
- DescType propCode;
- short startPos;
- short length;
- TETextTokenBody **tokHdl;
- Handle rawTextHdl;
- AEDesc replyValue;
- long rawSize;
- OSErr err;
- SignedByte hState;
-
- /* Sanity check */
- if ( tokenPtr->descriptorType != typeTEText ){
- Gripe( "\pGot wrong token type" );
- return errAEEventNotHandled;
- }
-
- tokHdl = (TETextTokenBody**)(tokenPtr->dataHandle);
-
- textH = (*tokHdl)->textH;
- propCode = (*tokHdl)->propertyCode;
- startPos = (*tokHdl)->startPos;
- length = (*tokHdl)->length;
-
- if ( !textH ){
- Gripe( "\pAttempting to get data for non-existent TextEdit Record" );
- return errAENoSuchObject;
- }
-
- switch ( propCode ){
- case typeNull:
- /* This is a magic number for "Not A Property". I don't know if this
- * is really kosher - gotta ask, but it is a convenience.
- */
-
- /* return all of the text in the specified range */
- rawTextHdl = (Handle)TEGetText( textH );
-
- /* Check the range to be sure the text is really there */
- rawSize = GetHandleSize( rawTextHdl );
-
- if ( rawSize < startPos + length ){
- return errAECorruptData;
- }
-
- hState = HGetState( rawTextHdl );
- HLock( rawTextHdl );
-
- err = AECreateDesc( typeChar,
- (char*)*rawTextHdl + startPos,
- (Size)length,
- &replyValue );
-
- HSetState( rawTextHdl, hState );
-
- if ( err ){
- Gripe( "\pAECreateDesc failed to create text replyValue" );
- return err;
- }
-
- break;
- case pClass:
- case pColor:
- case pFont:
- case pPointSize:
- case pScriptTag:
- case pTextStyles:
- Gripe( "\pGot a property type we do not yet implement" );
- return errAENoSuchObject;
- break;
- default:
- Gripe( "\pUnknown property type" );
- return errAENoSuchObject;
- break;
- }
-
- /* At this point we have some kind of descriptor to stick in the reply */
-
- err = AEPutParamDesc( replyEventPtr,
- keyDirectObject,
- &replyValue );
- if ( err ){
- Gripe( "\pAEPutParamDesc failed" );
- return err;
- }
-
- err = AEDisposeDesc( &replyValue );
- if ( err ){
- Gripe( "\pAEDisposeDesc failed" );
- return err;
- }
-
- return noErr;
- }/* TETextGetDataHandler */
-
- /* Set Data */
-
- OSErr TETextSetDataHandler( AEDesc *tokenPtr,
- AppleEvent *theAppleEventPtr,
- AppleEvent *replyEventPtr,
- long refCon )
- {
- TEHandle textH;
- DescType propCode;
- short startPos;
- short length;
- TETextTokenBody **tokHdl;
- AEDesc newValue;
- AEDesc textValue;
- AEDesc boolValue;
- SignedByte hState;
- long newTextLen;
- AEDesc propValToken;
- OSErr err;
-
- /* Sanity check */
- if ( tokenPtr->descriptorType != typeTEText ){
- Gripe( "\pGot wrong token type" );
- return errAEEventNotHandled;
- }
-
- tokHdl = (TETextTokenBody**)(tokenPtr->dataHandle);
-
- textH = (*tokHdl)->textH;
- propCode = (*tokHdl)->propertyCode;
- startPos = (*tokHdl)->startPos;
- length = (*tokHdl)->length;
-
- if ( !textH ){
- Gripe( "\pAttempting to set data for non-existent TextEdit Record" );
- return errAENoSuchObject;
- }
-
- /* Get the value to set, whatever it is */
-
- err = AEGetParamDesc( theAppleEventPtr,
- keyAEData,
- typeWildCard,
- &newValue );
- if ( err ){
- Gripe( "\pAEGetParamDesc failed to get keyAEData" );
- return err;
- }
-
- switch ( propCode ){
- case typeNull:
- /* This is a magic number for "Not A Property". I don't know if this
- * is really kosher - gotta ask, but it is a convenience.
- */
-
- /* Set the data in the specified range */
-
- /* STUB Look for the optional parameter to see where to actually
- * set the text at
- */
-
- err = AECoerceDesc( &newValue, typeChar, &textValue );
- if ( err ){
- Gripe( "\pAECoerceDesc failed to coerce to text" );
- return err;
- }
-
- TESetSelect( (long)startPos, (long)startPos + length, textH );
- TEDelete( textH );
-
- newTextLen = GetHandleSize( textValue.dataHandle );
-
- hState = HGetState( textValue.dataHandle );
- HLock( textValue.dataHandle );
-
- TEInsert( (Ptr)(*textValue.dataHandle), newTextLen, textH );
-
- gDocDirty = true;
-
- HSetState( textValue.dataHandle, hState );
-
- err = AEDisposeDesc( &textValue );
- if ( err ){
- Gripe( "\pAEDisposeDesc failed" );
- return err;
- }
-
- break;
-
- case pBackgroundHilite:
-
- /* Make sure that we have a boolean value */
-
- err = AECoerceDesc( &newValue, typeBoolean, &boolValue );
- if ( err ){
- Gripe( "\pAECoerceDesc failed to coerce to typeBoolean" );
- return err;
- }
-
- /* Set the selection in the TextEdit text */
-
- TESetSelect( startPos,
- startPos + length,
- textH );
-
- if ( *(Boolean*)(*boolValue.dataHandle) ){
- /* Display the selection, given that we are in the background */
-
- ShowSelection( textH );
-
- /* STUB we should get the window from the token */
- SetVertScroll( gDocWindow, gVertScroll );
-
- TEActivate( textH ); /* (Not normally done while in background) */
- }else{
- /* STUB This isn't really the best thing to do. What we really should
- * do is check to see whether we are the front process, and deactivate
- * if so. For this demo, we can reasonably assume that we are not
- * the front process.
- */
-
- TEDeactivate( textH );
- }
-
- return noErr;
- break;
-
- case pClass:
- case pColor:
- case pFont:
- case pPointSize:
- case pScriptTag:
- case pTextStyles:
- Gripe( "\pGot a property type we do not yet implement" );
- return errAENoSuchObject;
- break;
- default:
- Gripe( "\pUnknown property type" );
- return errAENoSuchObject;
- break;
- }
-
- /* At this point we are done with the newValue descriptor */
-
- err = AEDisposeDesc( &newValue );
-
- if ( err ){
- Gripe( "\pAEDisposeDesc newValue failed" );
- return err;
- }
-
- return noErr;
- }/* TETextSetDataHandler */
-
- /*
- * Object Accessors
- */
-
-
- /* Return a text token given a Window token */
-
- pascal OSErr TextFromWind(DescType desiredClass,
- const AEDesc *container,
- DescType containerClass,
- DescType form,
- const AEDesc *selectionData,
- AEDesc *theToken,
- long LongInt)
- {
- AEDesc longKeyData;
- WindowPtr wp;
- long count;
- TETextTokenBody tokData;
- OSErr err;
-
- /* Check that the container is what we intend. This should only happen if we
- * installed the token handler incorrectly.
- */
-
- if ( container->descriptorType != cWindow )
- return errAEEventNotHandled;
-
- /* find the window based on the key form */
-
- switch ( form ){
- case formAbsolutePosition:
- /* Make sure we really have a type long descriptor */
- err = AECoerceDesc( selectionData, typeLongInteger, &longKeyData );
- if ( err ){
- Gripe( "\pAECoerceDesc failed" );
- return err;
- }
-
- count = **(long**)(longKeyData.dataHandle);
-
- /* We're done with the descriptor created in the coercion */
-
- err = AEDisposeDesc( &longKeyData );
- if ( err ){
- Gripe( "\pAEDisposeDesc failed" );
- return err;
- }
-
- #ifndef HACK_OSPECS
- /* We only have one text field in the window */
-
- if ( count != 1 ){
- Gripe( "\pAttempting to get text from other than the first field" );
- return errAENoSuchObject;
- }
- #else
- /* Simulate the presence of two text blocks */
- if ( count != 1 && count != 2){
- Gripe( "\pAttempting to get text from other than the first field" );
- return errAENoSuchObject;
- }
- #endif
-
- wp = (*(WindTokenBody**)(container->dataHandle))->theWindowPtr;
-
- MakeTETextTokenBody( wp, &tokData, typeNull );
-
- err = AECreateDesc( typeTEText, (Ptr)&tokData, sizeof( tokData ), theToken );
- if ( err ){
- Gripe( "\pAECreateDesc failed to create a token" );
- return err;
- }
-
- return noErr;
- break;
- case formRelativePosition:
- case formTest:
- case formRange:
- case formPropertyID:
- Gripe( "\pGot a formPropertyID" );
- break;
- case formName:
- return errAEEventNotHandled; /* Flesh this out later */
- break;
- default:
- Gripe( "\pGot unexpected key form" );
- return errAEEventNotHandled;
- }
-
- return noErr;
- }
-
- void MakeTETextTokenBody( WindowPtr wp, TETextTokenBody* tokDataPtr, DescType propCode )
- {
- Handle rawTextHdl;
- short textLen;
- TEHandle textH;
-
- textH = (TEHandle)GetWRefCon( wp );
-
- rawTextHdl = (Handle)TEGetText( textH );
- textLen = (short)GetHandleSize( rawTextHdl );
-
- /* Actually create the token that we return */
- tokDataPtr->textH = textH;
- tokDataPtr->startPos = 0;
- tokDataPtr->length = textLen; /* _All_ of the text */
- tokDataPtr->propertyCode = typeNull; /* This means it's not a property */
-
- return;
- }
-
- /* return a word token from a TextEdit text token. The word is actually still a TEText */
-
- pascal OSErr WordFromTEText(DescType desiredClass,
- const AEDesc *container,
- DescType containerClass,
- DescType form,
- const AEDesc *selectionData,
- AEDesc *theToken,
- long LongInt)
- {
- AEDesc longKeyData;
- WindowPtr wp;
- long count;
- TETextTokenBody tokData;
- Handle rawTextHdl;
- char *textPtr;
- short i;
- short textLen;
- TEHandle textH;
- short oldPos;
- short newPos;
- short offSet;
- short oldLength;
- OSErr err;
-
- /* Check that the container is what we intend. This should only happen if we
- * installed the token handler incorrectly.
- */
-
- if ( container->descriptorType != typeTEText )
- return errAEEventNotHandled;
-
- /* find the text based on the key form */
-
- switch ( form ){
- case formAbsolutePosition:
- /* Make sure we really have a type long descriptor */
- err = AECoerceDesc( selectionData, typeLongInteger, &longKeyData );
- if ( err ){
- Gripe( "\pAECoerceDesc failed" );
- return err;
- }
-
- count = **(long**)(longKeyData.dataHandle);
-
- /* We're done with the descriptor created in the coercion */
-
- err = AEDisposeDesc( &longKeyData );
- if ( err ){
- Gripe( "\pAEDisposeDesc failed" );
- return err;
- }
-
- /* This is a really, really rude way to find a word. Assume that
- * each word is separated by just one space (we will really want to
- * allow for runs of spaces or other word-separating characters. The
- * following method is basically just plain wrong, but will suffice for
- * illustration.
- *
- * Also note that the first word in a block might come after a run of
- * spaces.
- */
-
- textH = (*(TETextTokenBody**)(container->dataHandle))->textH;
-
- rawTextHdl = (Handle)TEGetText( textH );
-
- oldPos = (*(TETextTokenBody**)(container->dataHandle))->startPos;
-
- textPtr = *rawTextHdl + oldPos; /* Deref'ed a handle! */
-
- oldLength = (*(TETextTokenBody**)(container->dataHandle))->length;
-
- for ( i = oldLength ; i; i-- ){
- if ( count == 0 ) /* Hmm... thought it was 1-based */
- break;
- if ( *textPtr++ == ' ' )
- count--;
- }
-
- if ( i == 0 ){
- Gripe( "\pRan off end of text before finding word" );
- return errAENoSuchObject;
- }
-
- offSet = oldLength - i;
-
- newPos = oldPos + offSet;
-
- /* now find the end of the word */
-
- textPtr = *rawTextHdl + newPos; /* Deref'ed a handle! */
-
- for ( i = oldLength - offSet ; i; i-- ){
- if ( *++textPtr == ' ' )
- break;
- }
-
- /* Actually create the token that we return */
- tokData.textH = textH;
- tokData.startPos = newPos;
- tokData.length = oldLength - offSet - i + 1;
- tokData.propertyCode = typeNull; /* This means it's not a property */
-
- err = AECreateDesc( typeTEText, (Ptr)&tokData, sizeof( tokData ), theToken );
- if ( err ){
- Gripe( "\pAECreateDesc failed to create a token" );
- return err;
- }
-
- return noErr;
- break;
- case formRelativePosition:
- case formTest:
- case formRange:
- case formPropertyID:
- case formName:
- return errAEEventNotHandled; /* Flesh this out later */
- break;
- default:
- Gripe( "\pGot unexpected key form" );
- return errAEEventNotHandled;
- }
-
- return noErr;
- }
-
- /* Return a textedit char token given a textedit text token */
-
- pascal OSErr CharFromTEText(DescType desiredClass,
- const AEDesc *container,
- DescType containerClass,
- DescType form,
- const AEDesc *selectionData,
- AEDesc *theToken,
- long LongInt)
- {
- AEDesc startSpec;
- AEDesc endSpec;
- AEDesc rangeRecord;
- AEDesc startToken;
- AEDesc endToken;
- long count;
- AEDesc longKeyData;
- TEHandle textH;
- Handle rawTextHdl;
- long numRawChars;
- TETextTokenBody tokData;
- short offset;
- OSErr err;
-
- /* Check that the container is what we intend. This should only happen if we
- * installed the token handler incorrectly.
- */
-
- if ( container->descriptorType != typeTEText )
- return errAEEventNotHandled;
-
- /* find the text based on the key form */
-
- switch ( form ){
- case formAbsolutePosition:
- /* Make sure we really have a type long descriptor */
- err = AECoerceDesc( selectionData, typeLongInteger, &longKeyData );
- if ( err ){
- Gripe( "\pAECoerceDesc failed" );
- return err;
- }
-
- count = **(long**)(longKeyData.dataHandle);
-
- /* We're done with the descriptor created in the coercion */
-
- err = AEDisposeDesc( &longKeyData );
- if ( err ){
- Gripe( "\pAEDisposeDesc failed" );
- return err;
- }
-
- textH = (*(TETextTokenBody**)(container->dataHandle))->textH;
-
- rawTextHdl = (Handle)TEGetText( textH );
-
- numRawChars = GetHandleSize( rawTextHdl );
-
- if ( count > 0 ){
- /* The position is relative to the beginning */
- if ( count > numRawChars ){
- Gripe( "\pAsked for character past end" );
- return errAENoSuchObject; /* Wanted char that was past end */
- }
-
- offset = (short) count;
-
- } else {
- /* In this case, the position is relative to the end of the text */
-
- if ( count < -numRawChars ){
- Gripe( "\pAsked for character before beginning" );
- return errAENoSuchObject;
- }
-
- offset = (short)(numRawChars + count); /* Note that count is negative */
- }
- /* Actually create the token that we return. */
-
- tokData.textH = textH;
- tokData.startPos = offset;
- tokData.length = 1; /* formAbs can have only 1 char */
- tokData.propertyCode = typeNull; /* This means it's not a property */
-
- err = AECreateDesc( typeTEText, (Ptr)&tokData, sizeof( tokData ), theToken );
- if ( err ){
- Gripe( "\pAECreateDesc failed to create a token" );
- return err;
- }
-
- return noErr;
- break;
- case formRelativePosition:
- return errAEEventNotHandled;
- break;
- case formTest:
- return errAEEventNotHandled;
- break;
- case formRange:
-
- /* We must coerce the spec to an AERecrd so GetKeyDesc will know what
- * to do with it.
- */
-
- err = AECoerceDesc( selectionData,
- typeAERecord,
- &rangeRecord );
- if ( err )
- return err;
-
- err = AEGetKeyDesc( &rangeRecord,
- keyAERangeStart,
- typeObjectSpecifier,
- &startSpec );
- if ( err ){
- Gripe( "\pAEGetKeyDesc failed" );
- return err;
- }
-
- err = AEGetKeyDesc( &rangeRecord,
- keyAERangeStop,
- typeObjectSpecifier,
- &endSpec );
- if ( err ){
- Gripe( "\pAEGetKeyDesc failed" );
- return err;
- }
-
- /* Now we have the object specifiers for the beginning and end of the
- * range. We call AEResolve to give us tokens for the items that are
- * at each end. Note that this causes two recursive calls to this very
- * function.
- */
-
- err = AEResolve( &startSpec, kAEIDoMinimum, &startToken );
- if ( err )
- return err;
-
- /* 1.1.1 MDC fix a memory leak */
-
- err = AEDisposeDesc( &startSpec );
- if ( err )
- return err;
-
- err = AEResolve( &endSpec, kAEIDoMinimum, &endToken );
- if ( err )
- return err;
-
- err = AEDisposeDesc( &endSpec );
- if ( err )
- return err;
-
-
-
- /* Create the return token */
- tokData.textH = (*(TETextTokenBody**)(container->dataHandle))->textH;
-
- tokData.startPos = (*(TETextTokenBody**)(startToken.dataHandle))->startPos;
-
- /* MDC 1.0d10 I have an off-by-one error in the speller's formAbsolutePosition
- * relative to the end, that makes 0 be the last character. It should
- * be -1. I should have added 1 here, which masked the bug.
- */
-
- tokData.length = 1 + (*(TETextTokenBody**)(endToken.dataHandle))->startPos -
- (*(TETextTokenBody**)(startToken.dataHandle))->startPos;
-
- tokData.propertyCode = typeNull; /* This means it's not a property */
-
- err = AECreateDesc( typeTEText, (Ptr)&tokData, sizeof( tokData ), theToken );
- if ( err ){
- Gripe( "\pAECreateDesc failed to create a token" );
- return err;
- }
-
- return noErr;
- break;
- case formPropertyID:
- return errAEEventNotHandled;
- break;
- case formName:
- return errAEEventNotHandled; /* Flesh this out later */
- break;
- default:
- Gripe( "\pGot unexpected key form" );
- return errAEEventNotHandled;
- }
-
- return noErr;
- }
-
- /* Return a property token given a textedit text token.
- * This works for any property of a textedit text item
- */
-
- pascal OSErr PropFromTEText(DescType desiredClass,
- const AEDesc *container,
- DescType containerClass,
- DescType form,
- const AEDesc *selectionData,
- AEDesc *theToken,
- long LongInt)
- {
- OSErr err;
- DescType propType;
-
- /* Check that the container is what we intend. This should only happen if we
- * installed the token handler incorrectly.
- */
-
- if ( container->descriptorType != typeTEText )
- return errAEEventNotHandled;
-
- if ( form != formPropertyID ){
- Gripe( "\pExpected formPropertyID" );
- return errAEEventNotHandled;
- }
-
- propType = **( (DescType**)(selectionData->dataHandle) );
-
- /* All we really do here is shove the property type into the token, if we
- * know about the property type
- */
-
- switch ( propType ){
- case pBackgroundHilite:
- /* This property contains a selection which is displayed while in the
- * background. All we do here is set the property code in the token
- * (This is done after the switch).
- */
- break;
- case pClass:
- case pColor:
- case pFont:
- case pPointSize:
- case pScriptTag:
- case pTextStyles:
- Gripe( "\pGot a property type we do not yet implement" );
- return errAENoSuchObject;
- break;
- default:
- Gripe( "\pUnknown property type" );
- return errAENoSuchObject;
- break;
- }
-
- /* All we do in the token is put the propType into it. We can start with the
- * container descriptor as it has some of the fields filled in already.
- */
-
- err = AEDuplicateDesc( container, theToken );
- if ( err ){
- Gripe( "\pAEDuplicateDesc failed" );
- return err;
- }
-
- (*(TETextTokenBody**)(theToken->dataHandle))->propertyCode = propType;
-
- return noErr;
- }
-
- /*
- * Utilities for creating object specifiers
- */
-
- OSErr CreateWindTextSpec( WindowPtr wp, long textNumber, AEDesc *specPtr )
- {
- WindowPtr candidate;
- long windowNumber;
- OSErr err;
-
- /* Search through the open windows (yes I know there's only one) looking
- * for the one matching the given pointer. This routine will be useful in
- * multiple-window programs.
- */
-
- if ( !wp )
- return errAENoSuchObject;
-
- candidate = FrontWindow();
-
- if ( !candidate )
- return errAENoSuchObject;
-
- windowNumber = 1;
-
- while ( candidate != wp ){
- candidate = (WindowPtr)((WindowPeek)candidate)->nextWindow;
- if ( !candidate )
- return errAENoSuchObject;
-
- windowNumber++;
- }
-
- err = CreateTextSpecifier( windowNumber, textNumber, specPtr );
-
- return err;
- }
-
- OSErr CreateTextSpecifier( long windowNumber, long textNumber, AEDesc *specPtr )
- {
- AEDesc docSpecifier;
- AEDesc textDescriptor;
- OSErr err;
-
- /* Create an object specifier for a particular text field within a particular
- * window. In each case use formAbsolutePosition.
- */
-
- err = BuildWindowSpecifier( &docSpecifier, windowNumber );
- if ( err ){
- Gripe( "\pBuildWindowDescriptor failed" );
- return err;
- }
-
- err = CreateOffsetDescriptor( textNumber, &textDescriptor );
- if ( err ){
- Gripe( "\pCreateOffsetDescriptor failed" );
- return err;
- }
-
- err = CreateObjSpecifier( cText,
- &docSpecifier,
- formAbsolutePosition,
- &textDescriptor,
- true, /* Dispose input descriptors */
- specPtr );
- if ( err ){
- Gripe( "\pCreateObjSpecifer failed" );
- return err;
- }
-
- return noErr;
- }
-
- /*
- * Object counting routines.
- */
-
- OSErr CountTextInWind( WindowPtr wp, long *countPtr )
- {
- /* For us, there can only be one text field in a window. If you have
- * a structured document such as a spreadsheet, you should count the total
- * number of text cells.
- */
-
- *countPtr = 1L;
-
- return noErr;
- }
-
-
- /*
- * Coercion handlers
- */
-
- /* Convert a pointer to raw text to a Pascal string. This is such a simple one it
- * ought to have been built into the system!
- */
-
- pascal OSErr TextPtrToPString( DescType typeCode,
- Ptr dataPtr,
- Size dataSize,
- DescType toType,
- long handlerRefCon,
- AEDesc *resultPtr )
- {
- char *buf;
- OSErr err;
- Ptr myDataPtr;
- Size myDataSize;
-
- if ( toType != typePString )
- return errAECoercionFail;
-
- /* This one routine could reasonably coerce from several different sorts of textual
- * data. We switch off the types and set a pointer to where the text data actually
- * starts. Don't have any "from" types but typeChar so far.
- */
-
- switch ( typeCode ){
- case typeChar:
- myDataPtr = dataPtr;
- myDataSize = dataSize;
- break;
- default:
- Gripe( "\pCannot coerce requested type" );
- return errAECoercionFail;
- break;
- }
-
- if ( myDataSize > 255 || myDataSize < 0 )
- return errAECoercionFail;
-
- buf = NewPtr( myDataSize + 1 );
- if ( !buf )
- return memFullErr;
-
- buf[0] = myDataSize;
- BlockMove( myDataPtr, &(buf[1]), dataSize );
-
- err = AECreateDesc( typePString,
- buf,
- myDataSize + 1,
- resultPtr );
-
- return err;
- }
-